﻿using System.Collections.Generic;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Drivers;
using SchoolPointe.RelatedContent.Models;
using SchoolPointe.RelatedContent.Services;
using SchoolPointe.RelatedContent.ViewModels;
using System.Linq;
using SchoolPointe.RelatedContent.Settings;
using Orchard.ContentManagement.Records;
using Orchard.ContentManagement.Handlers;
using Orchard.Data;
using System.Xml.Linq;

namespace SchoolPointe.RelatedContent.Drivers
{
    public class RelatedContentDriver : ContentPartDriver<RelatedContentPart>
    {
        private readonly IRelatedContentService _relatedContentService;
        private readonly IContentManager _contentManager;
        private IEnumerable<IRelatedContentDriver> _relatedContentDrivers;
        private IRepository<RelatedContentItemPartRecord> _relatedContentRepo;

        public RelatedContentDriver(
            IRelatedContentService relatedContentService, 
            IContentManager contentManager, 
            IEnumerable<IRelatedContentDriver> relatedContentDrivers,
            IRepository<RelatedContentItemPartRecord> relatedContentRepo)
        {
            _relatedContentService = relatedContentService;
            _contentManager = contentManager;
            _relatedContentDrivers = relatedContentDrivers;
            _relatedContentRepo = relatedContentRepo;
        }

        private IRelatedContentDriver GetDriver(string contentType, string relationshipIdentifier)
        {
            var driver = _relatedContentDrivers.FirstOrDefault(d => d.ContentType == contentType && d.RelationshipIdentifier == relationshipIdentifier);
            if (driver == null)
                driver = new DefaultRelatedContentDriver(_relatedContentService, _contentManager);
            return driver;
        }

        protected override string Prefix { get { return "RelatedContent"; } }

        protected override DriverResult Display(RelatedContentPart part, string displayType, dynamic shapeHelper)
        {
            var settings = new RelatedContentPartSettings(part.TypePartDefinition.Settings);
            var results = new List<DriverResult>();
            foreach (var relationship in settings.Relationships)
            {
                var driver = GetDriver(part.ContentItem.ContentType, relationship.Identifier);
                var relatedItems = _relatedContentService.GetRelatedItems(part, relationship);
                results.Add(driver.Display(part, relationship, relatedItems, displayType, shapeHelper));
            }
            return Combined(results.ToArray());
        }

        //GET
        protected override DriverResult Editor(RelatedContentPart part, dynamic shapeHelper)
        {
            return Editor(part, null, shapeHelper);
        }
        //POST
        protected override DriverResult Editor(RelatedContentPart part, IUpdateModel updater, dynamic shapeHelper)
        {
            var settings = new RelatedContentPartSettings(part.TypePartDefinition.Settings);
            var results = new List<DriverResult>();
            foreach (var relationship in settings.Relationships)
            {
                var driver = GetDriver(part.ContentItem.ContentType, relationship.Identifier);
                var relatedItems = _relatedContentService.GetRelatedItems(part, relationship);
                results.Add(driver.Editor(part, relationship, relatedItems, updater, shapeHelper));
            }
            return Combined(results.ToArray());
        }

        protected override void Imported(RelatedContentPart part, ImportContentContext context)
        {
            var relationships = context.Data.Element(part.PartDefinition.Name);
            if (relationships != null)
            {
                foreach (var relationship in relationships.Elements())
                {
                    var identifier = relationship.Attribute("Identifier").Value;
                    foreach (var relatedItem in relationship.Elements())
                    {
                        var relatedItemId = relatedItem.Attribute("RelatedItemId").Value;
                        var relatedContentItem = context.GetItemFromSession(relatedItemId);
                        if (relatedContentItem != null && relatedContentItem.Id > 0)
                            _relatedContentService.AddRelatedItem(part, identifier, relatedContentItem);
                        else
                            _relatedContentService.AddTemporaryRelatedItem(part, identifier, new ContentIdentity(relatedItemId));
                    }
                }
            }
        }

        protected override void Exporting(RelatedContentPart part, ExportContentContext context)
        {
            var relationships = _relatedContentRepo
                .Fetch(rc => rc.RelatedContentPartRecord == part.Record)
                .GroupBy(r => r.RelationshipIdentifier);

            var parent = context.Element(part.PartDefinition.Name);
            foreach (var relationshipGroup in relationships)
            {
                var groupXml = new XElement("ContentRelationship");
                groupXml.SetAttributeValue("Identifier", relationshipGroup.Key);
                foreach (var relationship in relationshipGroup)
                {
                    var relatedItem = new XElement("RelatedItem");
                    var relatedContentItem = _contentManager.Get(relationship.RelatedItem.Id);
                    relatedItem.SetAttributeValue("RelatedItemId", _contentManager.GetItemMetadata(relatedContentItem).Identity.ToString());
                    groupXml.Add(relatedItem);
                }
                parent.Add(groupXml);
            }
        }
    }
}